unit uSBDUnit_Executive;
interface
uses Classes, uSBDUnit_View, uSBDUnit_Controller, uSBDUnit_Model,
     Contnrs;
type

TUnitTestExecutive = class( TInterfacedPersistent)
  private
    FTestSuites: TArray<TPersistentClass>;
    FViews: TArray<IUnitTestView>;
    FOwnedObjects: TObjectList;

  protected
    procedure TestSuites( const Suites: array of TPersistentClass);
    procedure OwnIfNonCounted( const Element: IInterface);

  public
    constructor Create;
    destructor  Destroy; override;
    class function Instance: TUnitTestExecutive;       virtual; abstract;
    procedure StartUp;
    function  MakeViews: TArray<IUnitTestView>;        virtual;
    function  MakeController: IUnitTestController;     virtual;
    function  ControllingView: IUnitTestView;          virtual;
    procedure RegisterAllTestSuites;                   virtual;
  end;




implementation



uses SysUtils, uSBDUnit_Types, uSBDUnit_TestEngine;
{ TUnitTestExecutive }

function TUnitTestExecutive.ControllingView: IUnitTestView;
begin

end;

constructor TUnitTestExecutive.Create;
begin
FOwnedObjects := TObjectList.Create( True)
end;

destructor TUnitTestExecutive.Destroy;
begin
FOwnedObjects.Free;
inherited
end;

function TUnitTestExecutive.MakeController: IUnitTestController;
begin

end;

function TUnitTestExecutive.MakeViews: TArray<IUnitTestView>;
begin

end;


type TPersistentAccess = class( TPersistent) end;
function HasOwner( Obj: TPersistent): boolean;
begin
result := TPersistentAccess( Obj).GetOwner <> nil
end;


procedure TUnitTestExecutive.OwnIfNonCounted( const Element: IInterface);
var
  Obj: TObject;
begin
if (not assigned( Element)) or
   ((Element._AddRef + Element._Release) <> -2)
  then exit;
Obj := TObject( Element);
if ((not (Obj is TPersistent)) or (not HasOwner( Obj as TPersistent))) and
   (FOwnedObjects.IndexOf( Obj) = -1) then
  FOwnedObjects.Add( Obj)
end;


procedure TUnitTestExecutive.RegisterAllTestSuites;
begin

end;

procedure TUnitTestExecutive.StartUp;
var
  Eng: ITestEngine;
  Controller: IUnitTestController;
  j: integer;
  Registrar: ITestEngine_ViewRegistrar;
  MainView: IUnitTestView;
  Ctrl: IControllingView;
  ControllerFeedback: IControllerFeedback;
begin
Eng := TTestEngine.Create;
OwnIfNonCounted( Eng);
FViews := MakeViews;
Controller := MakeController;
if Supports( Eng, ITestEngine_ViewRegistrar, Registrar) then
  for j := 0 to Length( FViews) - 1 do
    begin
    Registrar.RegisterView( FViews[j]);
    OwnIfNonCounted( FViews[j])
    end;
Controller.SetModel( Eng);
Controller.SetCoDestroyObject( self);
if Supports( Controller, IControllerFeedback, ControllerFeedback) then
  Eng.SetControllerClient( ControllerFeedback);
MainView := ControllingView;
if Supports( MainView, IControllingView, Ctrl) then
  Ctrl.SetController( Controller);
SetLength( FTestSuites, 0);
RegisterAllTestSuites;
for j := 0 to Length( FTestSuites) - 1 do
  Eng.RegisterTestSuite( FTestSuites[j]);
SetLength( FTestSuites, 0);
SetLength( FViews, 0);
Eng.StartUp;
end;




procedure TUnitTestExecutive.TestSuites( const Suites: array of TPersistentClass);
var
  j: integer;
  L: integer;
begin
L := Length( FTestSuites);
SetLength( FTestSuites, L + Length( Suites));
for j := 0 to Length( Suites) - 1 do
  FTestSuites[ L + j] := Suites[j]
end;

end.
